package fnsvr

import (
	"math"
	"sort"
)

// 概率计算
type Probability struct {
	seed int64
}

// 获取当前种子
func (m *Probability) GetSeed() int64 {
	return m.seed
}

// 随机一次并返回本次随机是否命中概率
// v [0,1] 值越大命中概率越大
func (m *Probability) InFloatRate(v float64) bool {
	return m.Random() < v
}

// 洗牌
func Shuffle[T any](m *Probability, arr []T) {

	arrLen := float64(len(arr))
	if arrLen < 2 {
		return
	}

	var alen = int(math.Floor(arrLen / 2.0))
	if alen <= 0 {
		alen = 1
	}
	for i := 0; i < alen; i++ {
		var a = int(math.Floor(m.Random() * arrLen))
		var b = int(math.Floor(m.Random() * arrLen))
		var z = arr[a]
		arr[a] = arr[b]
		arr[b] = z
	}
}

// 随机产生一个浮点数 [0,1)
func (m *Probability) Random() float64 {
	m.seed = (m.seed*9301 + 49297) % 2013265919

	re := float64(m.seed) / 2013265919.0
	m.seed += 2013265919
	return re
}

// [0,n)
func (m *Probability) Intn(n int64) int64 {
	return int64(math.Floor(m.Random() * float64(n)))
}

// [a,b]
func (m *Probability) IntRange(a, b int64) int64 {
	if a == b {
		return a
	}
	var c = b - a
	return m.Intn(c+1) + a
}

// 在指定范围内随机cnt次，得到不同的cnt个数字，并排序返回
func (m *Probability) RangeIntMulti(min int64, max int64, cnt int) []int64 {
	ret := []int64{}
	if int(max-min+1) < cnt {
		cnt = int(max - min + 1)
	}

	rands := make(map[int64]bool)
	for len(ret) < cnt {
		var v = min + m.Intn(max-min+1)
		if !rands[v] {
			rands[v] = true
			ret = append(ret, v)
		}
	}

	sort.Slice(ret, func(i, j int) bool {
		return ret[i] < ret[j]
	})

	return ret
}

// 创建一个概率计算实例
func NewProbability(seed int64) *Probability {

	if seed == 0 {
		seed = 99999
	}
	if seed < 0 {
		seed = -seed
	}

	for seed < 2013265919 {
		seed *= 3
	}
	return &Probability{seed: seed}
}
